﻿#ifndef tk_serial_port_h
#define tk_serial_port_h

#include <QSerialPort>
#include "tk_mutex.h"
#include "tk_data_type.h"

namespace tk{
namespace io{

class TKSerialPort
{
public:
    TKSerialPort(){}

    ~TKSerialPort()
    {
        Close();
    }

    QString GetSerialPortName(tk_int32 port_num)
    {
#ifdef Q_OS_WIN
        if(port_num<10)
        {
            return QString("COM%1").arg(port_num);
        }
        else
        {
            return QString("\\\\.\\COM%1").arg(port_num);
        }
#else
        return QString("COM%1").arg(port_num);
#endif
    }

    tk_bool Open(QString port_name,
                 QSerialPort::BaudRate baud,
                 QSerialPort::DataBits databits,
                 QSerialPort::Parity parity,
                 QSerialPort::StopBits stopbits)
    {
        Close();

        TkMutexLocker locker(m_lock);
		
		m_serial_port.setPortName(port_name);
		tk_bool rt = m_serial_port.setBaudRate(baud); Q_ASSERT(rt);
		rt = m_serial_port.setParity(parity); Q_ASSERT(rt);
		rt = m_serial_port.setStopBits(stopbits); Q_ASSERT(rt);
		rt = m_serial_port.setDataBits(databits); Q_ASSERT(rt);
		m_serial_port.setReadBufferSize(1024);

        if(!m_serial_port.open(QIODevice::ReadWrite))
        {
            return TK_FALSE;
        }
        return TK_TRUE;
    }

    void Close()
    {
        TkMutexLocker locker(m_lock);
        m_serial_port.close();
    }

    bool Write(const tk_pchar pdata, tk_size_t len, tk_int32 time_out_ms)
    {
        TkMutexLocker locker(m_lock);
        if(!m_serial_port.isOpen())
        {
            return TK_FALSE;
        }
        Q_ASSERT(pdata);
        if(!(m_serial_port.write(pdata,qint64(len)) == qint64(len)) ||
			!m_serial_port.flush())
        {
            return TK_FALSE;
        }
        return TK_TRUE;
    }

    tk_size_t Read(tk_pchar pdata, tk_size_t max_len, tk_int32 time_out_ms)
    {
        TkMutexLocker locker(m_lock);
        if(!m_serial_port.isOpen())
        {
            return 0;
        }
		m_serial_port.waitForReadyRead(time_out_ms);
        {
			QByteArray data = m_serial_port.readAll();
			tk_size_t len = qMin(static_cast<tk_size_t>(data.size()), max_len);	
			if(len>0)
            {
				memcpy(pdata, data.data(), len);
                return len;
            }
        }
        return 0;
    }

protected:
private:
    QSerialPort m_serial_port;
    TkMutex m_lock;
};


}//namespace io
}//namespace tk

#endif // tk_serial_port_h
